package com.thermal.thermal_inspection.service.impl;

import com.thermal.thermal_inspection.entity.Inspection;
import com.thermal.thermal_inspection.entity.InspectionData;
import com.thermal.thermal_inspection.entity.Map;
import com.thermal.thermal_inspection.mapper.*;
import com.thermal.thermal_inspection.entity.InspectionWork;
import com.thermal.thermal_inspection.mapper.InspectionDataMapper;
import com.thermal.thermal_inspection.mapper.InspectionDetailMapper;
import com.thermal.thermal_inspection.mapper.InspectionMapper;
import com.thermal.thermal_inspection.mapper.InspectionWorkMapper;
import com.thermal.thermal_inspection.entity.*;
import com.thermal.thermal_inspection.service.BatchService;
import com.thermal.thermal_inspection.service.CacheService;
import com.thermal.thermal_inspection.service.InspectionService;
import com.thermal.thermal_inspection.service.UtilService;
import com.thermal.thermal_inspection.vo.*;
import com.thermal.thermal_inspection.vo.MapDetailVO;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class InspectionServiceImpl implements InspectionService {
    private static final Logger logger = Logger.getLogger(InspectionServiceImpl.class);

    // 虚拟环境中的 python 可执行文件路径
    String pythonInterpreter = "D:\\Python3.12.6\\python.exe";

    String basePath = "D:\\Tool\\nginx\\html";
    String scriptPath = "D:\\火电巡检系统开发\\cheat_detection\\main.py";

    //其他相关路径分别在741-743，784，797（提交数据接口），调用python在853行，取出保存图片相关路径在938,940行


    @Autowired
    CacheService cacheService;
    @Autowired
    StatisticsUserMapper statisticsUserMapper;


    //缓存过期时间单位
    static final int timeOut = 10;
    static final TimeUnit timeUnit = TimeUnit.MINUTES;

    @Autowired
    InspectionMapper inspectionMapper;
    @Autowired
    InspectionDataMapper inspectionDataMapper;
    @Autowired
    InspectionWorkMapper inspectionWorkMapper;
    @Autowired
    InspectionDetailMapper inspectionDetailMapper;
    @Autowired
    private MapDetailMapper mapDetailMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    MapMapper mapMapper;
    @Autowired
    ClassMapper classMapper;
    @Autowired
    RealNameMapper realNameMapper;
    @Autowired
    InspectionGroupMapper inspectionGroupMapper;
    @Autowired
    InspectionValueMapper inspectionValueMapper;
    @Autowired
    BatchMapper batchMapper;
    @Autowired
    UnitMapper unitMapper;
    @Autowired
    UtilService utilService;
    @Autowired
    BatchService batchService;

    @Value("${app.schedule-path}")
    private String scheduleDirPath;

    /**
     *判断是否存在巡检任务名
     */
    @Override
    public boolean existInspectionName(String inspectionName) {
        return inspectionMapper.getInspectionByName(inspectionName) != null;
    }

    /**
     * 新增巡检任务
     */
    @Override
    public int addInspection(String inspectionName, int inspectionUserId, int inspectionClassId, int inspectionMapId){
        Timestamp inspectionDate = new Timestamp(System.currentTimeMillis());
        return inspectionMapper.addInspection(inspectionName, inspectionDate, inspectionUserId, inspectionClassId, inspectionMapId);
    }

    /**
     * 通过巡检任务名获得巡检任务
     */
    @Override
    public Inspection getInspectionByName(String inspectionName){
        return inspectionMapper.getInspectionByName(inspectionName);
    }

    /**
     * 新增巡检任务详情
     */
    public int addInspectionData(int inspectionId, int inspectionGroupId, int mapDetailId, String inspectionDataDesc, String inspectionDataName){
        return inspectionDataMapper.addInspectionData(inspectionId, inspectionGroupId, mapDetailId, inspectionDataDesc, inspectionDataName);
    }
    /**
     * 判断分配的巡检任务名是否存在
     */
    @Override
    public boolean existInspectionWorkName(String inspectionWorkName){
        return inspectionWorkMapper.getInspectionWorkByName(inspectionWorkName) != null;
    }

    /**
     * 查看分配的模板任务是否存在
     */
    @Override
    public boolean existInspection(int inspectionId){
        return inspectionMapper.getInspectionById(inspectionId) != null;
    }

    /**
     * 新增inspection_work表
     */
    @Override
    public int addInspectionWork(Timestamp inspectionStartTime, int inspectionLimitTime, String inspectionWorkName,
                                 int inspectionId, int inspectionWorkNumber, int inspectionWorkStatus){
        return inspectionWorkMapper.addInspectionWork(inspectionStartTime, inspectionLimitTime, inspectionWorkName,
                inspectionId, inspectionWorkNumber, inspectionWorkStatus);
    }

    /**
     * 获取所有任务模版
     * @return List<Inspection>
     */
    @Override
    public List<Inspection> getAllInspectionTemplates() {
        return inspectionMapper.getAllInspectionTemplates();
    }

    /**
     * 获取所有任务模版详情
     * @return List<InspectionDataVO>
     */
    @Override
    public List<InspectionDataVO> getAllInspectionDataVOs(int inspectionId,int inspectionMapId) {
        List<InspectionData> inspectionDatas = inspectionDataMapper.getInspectionDataByInspectionId(inspectionId);
        System.out.println(inspectionDatas);
        List<MapDetailVO> mapDetailVOS = mapDetailMapper.getAllMapDetail(inspectionMapId);
        System.out.println(mapDetailVOS);
        //把这两个根据mapDetailId结合起来
        List<InspectionDataVO> inspectionDataVOS = new ArrayList<>();
        for (InspectionData inspectionData : inspectionDatas){
            for (MapDetailVO mapDetailVO : mapDetailVOS){
                if (inspectionData.getMapDetailId() == mapDetailVO.getMapDetailId()){
                    InspectionDataVO inspectionDataVO = new InspectionDataVO();
                    inspectionDataVO.setInspectionData(inspectionData);
                    inspectionDataVO.setMapDetailVO(mapDetailVO);
                    inspectionDataVOS.add(inspectionDataVO);
                    //删除已结合的点位
                    mapDetailVOS.remove(mapDetailVO);
                    break;
                }
            }
        }
        if (inspectionDataVOS.size() != inspectionDatas.size()){
            return null;
        }
            return inspectionDataVOS;
    }

    /**
     * 通过name获取inspection_work
     */
    @Override
    public InspectionWork getInspectionWorkByName(String inspectionWorkName){
        return inspectionWorkMapper.getInspectionWorkByName(inspectionWorkName);
    }

    /**
     * 插入inspection_detail表
     */
    @Override
    public int addInspectionDetail(int inspectionWorkId, int inspectionDataId, int inspectionDetailClass,
                                   int inspectionDetailUser, int inspectionDetailStatus,int inspectionGroupId,int mapDetailId,String inspectionDataDesc,String inspectionDataName,int unitId){
        return inspectionDetailMapper.addInspectionDetail(inspectionWorkId, inspectionDataId, inspectionDetailClass,
                inspectionDetailUser, inspectionDetailStatus,inspectionGroupId,mapDetailId,inspectionDataDesc,inspectionDataName,unitId);
    }

    /**
     * 查看分配的巡检任务
     */
    @Override
    public List<InspectionVO> getInspection(int userId){
        List<InspectionVO> inspectionVOList = new ArrayList<>();
        int role = userMapper.getRoleById(userId);
        if(role == 3) {
            //如果查询的人是编辑者，那么他只可以看到自己的巡检任务且若此时巡检任务的状态是未开始，则他们无法点击查看详情
            inspectionVOList.addAll(getInspectionVOById(userId));
            return inspectionVOList;
        }
        else {
            //若查询的人是根用户和管理员，那么他们可以看到全部的巡检任务并无论此时巡检任务的状态是什么他们都可以查看
            List<Integer> inspectionWorkIdList = inspectionWorkMapper.getInspectionWorkId();
            for(int inspectionWorkId:inspectionWorkIdList) {
                InspectionWork inspectionWork = inspectionWorkMapper.getInspectionWorkById(inspectionWorkId);
                Inspection inspection = inspectionMapper.getInspectionById(inspectionWork.getInspectionId());
                Map map = mapMapper.getMap(inspection.getInspectionMapId());
                InspectionVO inspectionVO = new InspectionVO(map, inspection, inspectionWork);
                inspectionVOList.add(inspectionVO);
            }

            LinkedHashSet<InspectionVO> hashSet = new LinkedHashSet<>(inspectionVOList);
            List<InspectionVO> list = new ArrayList<>(hashSet);
            return list;
        }
    }

    //编辑者通过userId查询对应的inspectionVO
    List<InspectionVO> getInspectionVOById(int userId){
        //先通过userId获取所有的巡检任务InspectionWork,然后每个inspectionWork都可以获取到对应的inspection和map
        List<InspectionVO> inspectionVOList = new ArrayList<>();
        List<Integer> inspectionWorkIdList = inspectionDetailMapper.getInspectionWorkIdByUserId(userId);
        List<Integer> startInspectionWorkIdList = new ArrayList<>();
        //排除掉状态为4未开始的任务
        for(int inspectionWorkId:inspectionWorkIdList){
            if(inspectionWorkMapper.getInspectionWorkById(inspectionWorkId).getInspectionWorkStatus() != 4)
                startInspectionWorkIdList.add(inspectionWorkId);
        }
        for(int inspectionWorkId:startInspectionWorkIdList) {
            InspectionWork inspectionWork = inspectionWorkMapper.getInspectionWorkById(inspectionWorkId);
            //inspectionWork中的inspectionWorkNumber和inspectionWorkFinish需要根据特定用户进行查询
            int userInspectionWorkNumber = inspectionDetailMapper.getUserInspectionWorkNumber(userId, inspectionWork.getInspectionWorkId());
            int userInspectionWorkFinish = inspectionDetailMapper.getUserInspectionWorkFinish(userId, inspectionWork.getInspectionWorkId());
            inspectionWork.setInspectionWorkNumber(userInspectionWorkNumber);
            inspectionWork.setInspectionWorkFinish(userInspectionWorkFinish);
            Inspection inspection = inspectionMapper.getInspectionById(inspectionWork.getInspectionId());
            Map map = mapMapper.getMap(inspection.getInspectionMapId());
            InspectionVO inspectionVO = new InspectionVO(map, inspection, inspectionWork);
            inspectionVOList.add(inspectionVO);
        }
        return inspectionVOList;
    }

    /**
     * 查看分配的巡检任务详情
     */
    @Override
    public List<InspectionDetailVO> getInspectionDetail(int inspectionWorkId, int userId){
        List<InspectionDetailVO> inspectionDetailVOList = new ArrayList<>();
        int role = userMapper.getRoleById(userId);
        if(role == 3) {
            //如果此时查看的用户是编辑者，那么他们只能查看自己的巡检点位任务且需要经过nfc签到才能解锁对应巡检点位任务，然后他才能填数据并保存。
            List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByWorkIdAndUser(inspectionWorkId, userId);
            return getInspectionDetailVOList(inspectionDetailList);
        }
        else {
            //如果此时查看的用户是管理员和根用户，那么他们的可以查看此巡检任务的所有巡检点位任务且无需NFC签到就可以查看巡检点位任务的详情
            List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByWorkId(inspectionWorkId);
            return getInspectionDetailVOList(inspectionDetailList);
        }
    }

    //通过inspectionDataList,inspectionDetailList,mapDetailList三张表查询出inspectionDetailVOList
    private List<InspectionDetailVO> getInspectionDetailVOList(List<InspectionDetail> inspectionDetailList){
        //inspectionDataList:
        //inspectionDetailList:
        //mapDetailList:
        List<InspectionDetailVO> inspectionDetailVOList = new ArrayList<>();
        System.out.println(inspectionDetailList);

            for(InspectionDetail inspectionDetail:inspectionDetailList){
                InspectionDetailVO inspectionDetailVO = new InspectionDetailVO();

                //inspectionDetail属性
                inspectionDetailVO.setInspectionDetailId(inspectionDetail.getInspectionDetailId());
                inspectionDetailVO.setInspectionDetailCheatmsg(inspectionDetail.getInspectionDetailCheatmsg());
                inspectionDetailVO.setInspectionDetailClassId(inspectionDetail.getInspectionDetailClass());
                inspectionDetailVO.setInspectionDetailClass(classMapper.getNameById(inspectionDetail.getInspectionDetailClass()));
                inspectionDetailVO.setInspectionDetailId(inspectionDetail.getInspectionDetailId());
                System.out.println(inspectionDetail.getInspectionDetailId());
                //从inspectionValue取值
                List<InspectionValue> inspectionValues = inspectionValueMapper.getValueByDetailId(inspectionDetail.getInspectionDetailId());
                List<InspectionGroupDetail> inspectionGroupDetails = inspectionGroupMapper.getInspectionGroupDetails(inspectionDetail.getInspectionGroupId());
                List<InspectionValueVo> inspectionValueVos = new ArrayList<>();
                String inspectionGroupName = inspectionGroupMapper.getInspectionGroupByInspectionId(inspectionDetail.getInspectionGroupId()).getInspectionGroupName();
                for (InspectionValue inspectionValue:inspectionValues){
                    InspectionValueVo inspectionValueVo = new InspectionValueVo();
                    inspectionValueVo.setInspectionGroupName(inspectionGroupName);
                    inspectionValueVo.setGroupValue(inspectionValue.getGroupValue());
                    inspectionValueVo.setGroupDetailId(inspectionValue.getGroupDetailId());
                    inspectionValueVo.setInspectionGroupId(inspectionDetail.getInspectionGroupId());
                    for (InspectionGroupDetail inspectionGroupDetail : inspectionGroupDetails){
                        if (inspectionGroupDetail.getGroupDetailId() == inspectionValue.getGroupDetailId()){
                            inspectionValueVo.setAttribute(inspectionGroupDetail.getAttribute());
                            inspectionValueVo.setPerUnit(inspectionGroupDetail.getPerUnit());
                            break;
                        }
                    }
                    inspectionValueVos.add(inspectionValueVo);
                }
                inspectionDetailVO.setInspectionValueVos(inspectionValueVos);

                inspectionDetailVO.setInspectionDetailImg(inspectionDetail.getInspectionDetailImg());
                inspectionDetailVO.setInspectionDetailIscheat(inspectionDetail.getInspectionDetailIscheat());
                inspectionDetailVO.setInspectionDetailScore(inspectionDetail.getInspectionDetailScore());
                inspectionDetailVO.setInspectionDetailStatus(inspectionDetail.getInspectionDetailStatus());
                inspectionDetailVO.setInspectionDetailUserId(inspectionDetail.getInspectionDetailUser());
                inspectionDetailVO.setInspectionDetailUser(realNameMapper.getRealNameByUserId(inspectionDetail.getInspectionDetailUser()).getRealName());
                inspectionDetailVO.setInspectionEndTime(inspectionDetail.getInspectionEndTime());
                inspectionDetailVO.setInspectionWorkId(inspectionDetail.getInspectionWorkId());
                inspectionDetailVO.setInspectionDetailNote(inspectionDetail.getInspectionDetailNote());
                inspectionDetailVO.setInspectionDataDesc(inspectionDetail.getInspectionDataDesc());
                inspectionDetailVO.setInspectionDataName(inspectionDetail.getInspectionDataName());
                inspectionDetailVO.setInspectionGroupId(inspectionDetail.getInspectionGroupId());

                //设置map相关属性
                int mapDetailId = inspectionDetail.getMapDetailId();
                inspectionDetailVO.setMapDetailId(mapDetailId);

                MapDetail mapDetail = mapDetailMapper.getMapDetailById(inspectionDetail.getMapDetailId());
                String unitName = unitMapper.selectUnit(mapDetail.getUnitId()).getUnitName();

                //mapDetail属性
                inspectionDetailVO.setMapId(mapDetail.getMapId());
                inspectionDetailVO.setMapLatitude(mapDetail.getMapLatitude());
                inspectionDetailVO.setMapLongitude(mapDetail.getMapLongitude());
                inspectionDetailVO.setUnitName(unitName);
                inspectionDetailVO.setMapNfcMsg(mapDetail.getMapNfcMsg());
                inspectionDetailVO.setMapDetailId(mapDetail.getMapDetailId());
                inspectionDetailVO.setMapDetailDesc(mapDetail.getMapDetailDesc());

                //最后添加到inspectionDetailVOList里面
                inspectionDetailVOList.add(inspectionDetailVO);
        }
        LinkedHashSet<InspectionDetailVO> hashSet = new LinkedHashSet<>(inspectionDetailVOList);
        List<InspectionDetailVO> list = new ArrayList<>(hashSet);
        return list;
    }

    /**
     * 修改巡检任务模板
     */
    @Override
    public Inspection changeInspection(int inspectionId, int inspectionMapId, String inspectionName, int inspectionUserId, int inspectionClassId){
        int rows = inspectionMapper.changeInspection(inspectionId, inspectionMapId, inspectionName, inspectionUserId, inspectionClassId);
        if(rows == 0)
            return null;
        return inspectionMapper.getInspectionById(inspectionId);
    }

    /**
     * 判断巡检任务详情是否存在
     */
    @Override
    public boolean existInspectionData(int inspectionDataId){
        return inspectionDataMapper.getInspectionDataById(inspectionDataId) != null;
    }

    /**
     * 修改任务详情
     */
    @Override
    public InspectionData changeInspectionData(int inspectionDataId, int inspectionId, int inspectionGroupId, int mapDetailId, String inspectionDataDesc, String inspectionDataName){
        int rows = inspectionDataMapper.changeInspectionData(inspectionDataId, inspectionId, inspectionGroupId, mapDetailId, inspectionDataDesc, inspectionDataName);
        if(rows == 0)
            return null;
        return inspectionDataMapper.getInspectionDataById(inspectionDataId);
    }

    /**
     * 删除巡检模板任务
     */
    @Override
    public int deleteInspection(int inspectionId){
        int rows1 = inspectionMapper.deleteInspection(inspectionId);
        int rows2 = inspectionDataMapper.deleteInspection(inspectionId);
        return rows1;
    }

    /**
     * 判断分配任务是否存在
     */
    @Override
    public boolean existInspectionWork(int inspectionWorkId){
        return inspectionWorkMapper.getInspectionWorkById(inspectionWorkId) != null;
    }

    /**
     * 删除分配巡检任务
     */
    @Override
    public int deleteInspectionWork(int inspectionWorkId){
        int rows1 = inspectionWorkMapper.deleteInspectionWork(inspectionWorkId);
        int rows2 = inspectionDetailMapper.deleteInspectionWork(inspectionWorkId);
        batchMapper.deleteBatchByWorkId(inspectionWorkId);
        return rows1;
    }

    /**
     * 任务搜索
     */
    @Override
    public List<InspectionVO> searchInspection(int userId, Timestamp startTime, Timestamp endTime, int searchUserId, int mapId){
        List<InspectionVO> inspectionVOList = new ArrayList<>();
        int role = userMapper.getRoleById(userId);
        if(role == 1 || role == 2){
            //管理员可以查看任意用户的任务
            logger.info("查看" + searchUserId + "用户任务");
            return getSearchInspectionVO(startTime, endTime, searchUserId, mapId, role, userId);
        }else {
            //其他用户则只能查看自己的任务
            if(searchUserId != -1 && userId != searchUserId) {
                logger.error("不能查看其他人的任务");
                return inspectionVOList;
            }
            return getSearchInspectionVO(startTime, endTime, searchUserId, mapId, role, userId);
        }
    }

    /**
     *通过时间，用户id，地图id查询inspectionVOList
     */
    private List<InspectionVO> getSearchInspectionVO(Timestamp startTime, Timestamp endTime ,int searchUserId, int mapId, int role, int userId){
        List<InspectionVO> inspectionVOList = new ArrayList<>();

        Date startDate = new Date(startTime.getTime());
        Date endDate = new Date(endTime.getTime());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedStartDate = calendar.getTime();  // 获取调整后的时间

        calendar.setTime(endDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedEndDate = calendar.getTime();  // 获取调整后的时间

        //这里要分四种情况，searchUserId,mapId都有可能为-1
        if(searchUserId != -1 && mapId != -1) {
            //当用户id和mapId都不为-1时
            List<InspectionWork> inspectionWorkList = inspectionWorkMapper.getInspectionWorkByTime(adjustedStartDate, adjustedEndDate);
            //这里对地图和任务详情进行了联合查询
            List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByUserAndMap(searchUserId, mapId);

            // 创建一个 Set 来存储 inspectionDetailList 中的所有 inspection_work_id
            Set<Integer> inspectionWorkIdSet = inspectionDetailList.stream()
                    .map(InspectionDetail::getInspectionWorkId)
                    .collect(Collectors.toSet());

            // 在 inspectionWorkList 中过滤出符合条件的 InspectionWork
            List<InspectionWork> filteredInspectionWorkList = inspectionWorkList.stream()
                    .filter(work -> inspectionWorkIdSet.contains(work.getInspectionWorkId()))
                    .collect(Collectors.toList());

            for(InspectionWork inspectionWork:filteredInspectionWorkList){
                //此时确定了唯一的inspectionWork, inspection, map
                //然后查看role是否为3，如果为3,则将inspectionWork的inspectionWorkNumber改为searchUserId在inspectionDetail表中的数量
                if(role == 3)
                    inspectionWork.setInspectionWorkNumber(inspectionDetailMapper.getInspectionWorkUserNumber(inspectionWork.getInspectionWorkId(), searchUserId));
                InspectionVO inspectionVO = new InspectionVO(mapMapper.getMap(mapId), inspectionMapper.getInspectionById(inspectionWork.getInspectionId()), inspectionWork);
                inspectionVOList.add(inspectionVO);
            }
            LinkedHashSet<InspectionVO> hashSet = new LinkedHashSet<>(inspectionVOList);
            List<InspectionVO> list = new ArrayList<>(hashSet);
            return list;
        }else if (searchUserId == -1 && mapId != -1){
            //查询某张地图某天的所有任务
            List<Inspection> inspectionList = inspectionMapper.getInspectionByMap(mapId);
            List<InspectionWork> inspectionWorkList = inspectionWorkMapper.getInspectionWorkByTime(adjustedStartDate, adjustedEndDate);

            for(Inspection inspection:inspectionList){
                for(InspectionWork inspectionWork:inspectionWorkList){
                    if(inspection.getInspectionId() == inspectionWork.getInspectionId()){
                        //此时再判断role是否为3，如果为3，则将inspectionWork的inspectionWorkNumber改为这个user在表中的数量
                        if(role == 3){
                            inspectionWork.setInspectionWorkNumber(inspectionDetailMapper.getInspectionWorkUserNumber(inspectionWork.getInspectionWorkId(), userId));
                            //如果这个inspectionWork对应的inspectionDetail中，没有一个是这个user的，那就跳过
                            List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByWorkId(inspectionWork.getInspectionWorkId());
                            boolean userExists = inspectionDetailList.stream()
                                    .anyMatch(detail -> detail.getInspectionDetailUser()==userId);
                            if(!userExists)
                                continue;
                        }
                        InspectionVO inspectionVO = new InspectionVO(mapMapper.getMap(mapId), inspection, inspectionWork);
                        inspectionVOList.add(inspectionVO);
                    }
                }
            }
            LinkedHashSet<InspectionVO> hashSet = new LinkedHashSet<>(inspectionVOList);
            List<InspectionVO> list = new ArrayList<>(hashSet);
            return list;
        }else if (searchUserId != -1 && mapId == -1){
            //查询某天某人的所有任务
            List<InspectionWork> inspectionWorkList = inspectionWorkMapper.getInspectionWorkByTime(adjustedStartDate, adjustedEndDate);
            List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByUserId(searchUserId);
            for(InspectionWork inspectionWork:inspectionWorkList){
                for(InspectionDetail inspectionDetail:inspectionDetailList){
                    if(inspectionWork.getInspectionWorkId() == inspectionDetail.getInspectionWorkId()){
                        Inspection inspection = inspectionMapper.getInspectionById(inspectionWork.getInspectionId());
                        //此时再判断role是否为3，如果为3，则将inspectionWork的inspectionWorkNumber改为这个user在表中的数量
                        if(role == 3){
                            inspectionWork.setInspectionWorkNumber(inspectionDetailMapper.getInspectionWorkUserNumber(inspectionWork.getInspectionWorkId(), searchUserId));
                        }
                        InspectionVO inspectionVO = new InspectionVO(mapMapper.getMap(inspection.getInspectionMapId()), inspection, inspectionWork);
                        inspectionVOList.add(inspectionVO);
                    }
                }
            }
            LinkedHashSet<InspectionVO> hashSet = new LinkedHashSet<>(inspectionVOList);
            List<InspectionVO> list = new ArrayList<>(hashSet);
            return list;
        }else {
            //查询某天的所有任务
            List<InspectionWork> inspectionWorkList = inspectionWorkMapper.getInspectionWorkByTime(adjustedStartDate, adjustedEndDate);
            for(InspectionWork inspectionWork:inspectionWorkList){
                Inspection inspection = inspectionMapper.getInspectionById(inspectionWork.getInspectionId());
                //此时再判断role是否为3，如果为3，则将inspectionWork的inspectionWorkNumber改为这个user在表中的数量
                if(role == 3){
                    inspectionWork.setInspectionWorkNumber(inspectionDetailMapper.getInspectionWorkUserNumber(inspectionWork.getInspectionWorkId(), userId));
                    //如果这个inspectionWork对应的inspectionDetail中，没有一个是这个user的，那就跳过
                    List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByWorkId(inspectionWork.getInspectionWorkId());
                    boolean userExists = inspectionDetailList.stream()
                            .anyMatch(detail -> detail.getInspectionDetailUser()==userId);
                    if(!userExists)
                        continue;
                }
                InspectionVO inspectionVO = new InspectionVO(mapMapper.getMap(inspection.getInspectionMapId()), inspection, inspectionWork);
                inspectionVOList.add(inspectionVO);
            }
            LinkedHashSet<InspectionVO> hashSet = new LinkedHashSet<>(inspectionVOList);
            List<InspectionVO> list = new ArrayList<>(hashSet);
            return list;
        }
    }

    /**
     * 查找用户巡查，异常，漏检，不合格数
     */
    public StatusNumVO getStatusNumVO(int userId){
        return statisticsUserMapper.getStatusNumVOByUserId(userId);
    }

    /**
     * 定期更新用户巡查，异常，漏检，不合格数缓存，每10分钟更新一次
     **/
    @Override
    @Scheduled(fixedRate = 10 * 60 * 1000)
    public void updateCacheStatusNumVO(){
        //先获取用户id列表
        List<Integer> idList = inspectionDetailMapper.getAllUserId();
        //进行去重
        LinkedHashSet<Integer> hashSet = new LinkedHashSet<>(idList);
        List<Integer> list = new ArrayList<>(hashSet);
        //使用并行流实现异步更新
        list.parallelStream().forEach(userId -> {
            StatusNumVO statusNumVO = getStatusNumVO(userId);
            cacheService.put("userIdStatus:" + userId, statusNumVO, timeOut, timeUnit);
        });
        logger.info("更新用户巡查，异常，漏检，不合格数缓存");
    }

    // Timestamp 转 LocalDateTime 的方法
    private static LocalDateTime toLocalDateTime(Timestamp timestamp) {
        return timestamp.toLocalDateTime();
    }

    /**
     * 查找用户本周，本季，本月，本年未巡检数
     */
    @Override
    public NonInspectionVO getNonInspection(int userId){
        if(userMapper.getUserByUserId(userId) == null){
            logger.error("该成员不存在");
            return null;
        }
        NonInspectionVO nonInspectionVO = new NonInspectionVO();

        LocalDateTime now = LocalDateTime.now();

        // 获取本周的周一 00:00:00
        LocalDateTime startOfWeek = now.with(DayOfWeek.MONDAY).toLocalDate().atStartOfDay();

        // 获取本月的 1 号 00:00:00
        LocalDateTime startOfMonth = now.withDayOfMonth(1).toLocalDate().atStartOfDay();

        // 获取本季的开始时间（假设季度开始时间是1月、4月、7月、10月）
        int currentMonth = now.getMonthValue();
        LocalDateTime startOfQuarter = LocalDateTime.of(
                now.getYear(),
                (currentMonth - 1) / 3 * 3 + 1, // 每季度的第一月
                1,
                0, 0, 0, 0
        );

        // 获取本年的 1 月 1 号 00:00:00
        LocalDateTime startOfYear = LocalDateTime.of(now.getYear(), 1, 1, 0, 0, 0, 0);

        //本周未巡检
        List<StatisticsUser> weekStatistic = statisticsUserMapper.getUserNonStatistic(userId, Timestamp.valueOf(startOfWeek));
        //本月未巡检
        List<StatisticsUser> monthStatistic = statisticsUserMapper.getUserNonStatistic(userId, Timestamp.valueOf(startOfMonth));
        //本季未巡检
        List<StatisticsUser> quarterStatistic = statisticsUserMapper.getUserNonStatistic(userId, Timestamp.valueOf(startOfQuarter));
        //本年未巡检
        List<StatisticsUser> yearStatistic = statisticsUserMapper.getUserNonStatistic(userId, Timestamp.valueOf(startOfYear));

        int weekTotal = weekStatistic.stream().mapToInt(user -> user.getTimeout() + user.getProcessing()).sum();
        int monthTotal = monthStatistic.stream().mapToInt(user -> user.getTimeout() + user.getProcessing()).sum();
        int quarterTotal = quarterStatistic.stream().mapToInt(user -> user.getTimeout() + user.getProcessing()).sum();
        int yearTotal = yearStatistic.stream().mapToInt(user -> user.getTimeout() + user.getProcessing()).sum();

        //构造返回值
        return new NonInspectionVO(weekTotal, monthTotal, quarterTotal, yearTotal);
    }

    /**
     * 定期更新用户本周本季本月本年未巡检数缓存（1天）
     */
    @Override
    @Scheduled(fixedRate = 60000*60*24)
    public void updateCacheNonInspection(){
        //先获取用户id列表
        List<Integer> idList = inspectionDetailMapper.getAllUserId();
        //进行去重
        LinkedHashSet<Integer> hashSet = new LinkedHashSet<>(idList);
        List<Integer> list = new ArrayList<>(hashSet);
        //使用并行流实现异步更新
        list.parallelStream().forEach(userId -> {
            NonInspectionVO nonInspectionVO = getNonInspection(userId);
            cacheService.put("userIdNonInspection:" + userId, nonInspectionVO, timeOut, timeUnit);
        });
        logger.info("更新用户本周本季本月本年未巡检数缓存");
    }

    /**
     * 根据创建者or模板名称or负责班组搜索模板
     */
    @Override
    public List<Inspection> searchInspectionTemplate(String inspectionName, Integer inspectionUserId, Integer inspectionClassId){
        return inspectionMapper.searchInspectionTemplate(inspectionName, inspectionUserId, inspectionClassId);
    }

    /**
     * 定时更新分配的巡检任务状态
     */
    @Override
    @Scheduled(fixedRate = 10 * 1000)
    public void updateCacheInspectionWorkStatus(){
        List<InspectionWork> finishingInspectionWorkList = getFinishingInspectionWork();
        List<InspectionWork> startInspectionWorkList = getStartInspectionWorkList();

        //未开始（4）和处理中（0）任务分开判断，看是否需要改变状态
        for(InspectionWork inspectionWork: startInspectionWorkList) {
            //未开始任务（4），先判断是否达到开始时间，然后判断是否达到截止时间
            Timestamp now = Timestamp.from(Instant.now());
            Timestamp inspectionStartTime = inspectionWork.getInspectionStartTime();
            if (inspectionStartTime.before(now)) {
                // 已经过了开始时间，接下来判断是否达到截止时间
                // 将 endTime 转换为 Instant
                Instant endInstant = inspectionWork.getInspectionStartTime().toInstant();
                // 使用 Duration 增加小时
                Instant newInstant = endInstant.plus(Duration.ofHours(inspectionWork.getInspectionLimitTime()));
                // 将新的 Instant 转换回 Timestamp
                Timestamp inspectionEndTime = Timestamp.from(newInstant);
                if (inspectionEndTime.after(now)) {
                    //没有到达截止时间，状态变成0处理中，同时将里面的点位状态也改成处理中
                    inspectionWorkMapper.setStatus(0, inspectionWork.getInspectionWorkId());
                    List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByWorkId(inspectionWork.getInspectionWorkId());
                    for(InspectionDetail inspectionDetail: inspectionDetailList)
                        inspectionDetailMapper.setStatus(inspectionDetail.getInspectionDetailId(), 0);
                } else {
                    //过了截止时间，此时就要判断这个任务的所有分配任务，如果有分配任务状态为0的则状态变为1，没有则变为2
                    //todo 这里做了修改
                    inspectionWorkMapper.setStatus(1, inspectionWork.getInspectionWorkId());
                    if(inspectionWork.getInspectionWorkNumber() == inspectionWork.getInspectionWorkFinish())
                        inspectionWorkMapper.setStatus(2, inspectionWork.getInspectionWorkId());
                }
            }
            //还没有开始，状态不用变
        }

        for(InspectionWork inspectionWork1: finishingInspectionWorkList){
            //处理中任务,判断是否达到截止时间
            LocalDateTime finishLocalDateTime = inspectionWork1.getInspectionStartTime().toLocalDateTime().plusHours(inspectionWork1.getInspectionLimitTime());
            Timestamp finishTime = Timestamp.valueOf(finishLocalDateTime);
            if(finishTime.toInstant().isBefore(Instant.now())){
                //已超时，此时就要判断这个任务的所有分配任务，如果有分配任务状态为0的则状态变为1，没有则变为2
//                inspectionWorkMapper.setStatus(1, inspectionWork1.getInspectionWorkId());
//                LocalDateTime now = LocalDateTime.now();  // 获取当前时间（LocalDateTime）
//                Timestamp timestamp = Timestamp.valueOf(now);  // 将LocalDateTime转换为Timestamp
//                inspectionWorkMapper.setEndTime(timestamp, inspectionWork1.getInspectionWorkId());
                List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByWorkId(inspectionWork1.getInspectionWorkId());
                for(InspectionDetail inspectionDetail:inspectionDetailList){
                    //todo 这里做了修改
                    if(inspectionDetail.getInspectionDetailStatus() == 0 || inspectionDetail.getInspectionDetailStatus() == 6) {
                        inspectionWorkMapper.setStatus(1, inspectionWork1.getInspectionWorkId());
//                        inspectionWorkMapper.setEndTimeNull(inspectionWork1.getInspectionWorkId());
                    }
                }
            }
        }
    }

    /**
     * 获取处理中任务
     */
    @Override
    public List<InspectionWork> getFinishingInspectionWork(){
        List<InspectionWork> inspectionWorkList = inspectionWorkMapper.getFinishingInspectionWork();
        if(inspectionWorkList.isEmpty() || inspectionWorkList == null){
            return new ArrayList<>();
        }
        return inspectionWorkList;
    }

    /**
     * 获取未完成任务
     */
    @Override
    public List<InspectionWork> getStartInspectionWorkList(){
        List<InspectionWork> inspectionWorkList = inspectionWorkMapper.getStartInspectionWork();
        if(inspectionWorkList.isEmpty() || inspectionWorkList == null){
            return new ArrayList<>();
        }
        return inspectionWorkList;
    }

    /**
     * 提交数据
     */
    @Override
    public int submitInspection(int inspectionDetailId, int inspectionGroupId, List<TextVO> textVOList  , MultipartFile[] images, MultipartFile cheatMsg, boolean isAbnormal) throws IOException {
        List<String> attributeList = inspectionGroupMapper.getAscAttributeByGroupId(inspectionGroupId);
        List<String> valueList = new ArrayList<>();
        String inspectionDataValue = "";

        String inspectionFolder = basePath + "\\" + "inspectionDetailId" + inspectionDetailId;
        String imagesFolder = inspectionFolder + "\\" + "images";
        String cheatMsgFolder = inspectionFolder + "\\" + "cheatMsg";

        int minDb = 40;
        int maxDb = 60;
        int rows1 = 1;

        //插入数据值
        for (TextVO textVO : textVOList){
            InspectionValue inspectionValue = new InspectionValue();
            inspectionValue.setInspectionGroupId(inspectionGroupId);
            inspectionValue.setInspectionDetailId(inspectionDetailId);
            inspectionValue.setGroupValue(textVO.getValue());
            inspectionValue.setGroupDetailId(textVO.getGroupDetailId());
            rows1 = inspectionValueMapper.insertValues(inspectionValue);
        }

        //设置巡检点位任务完成时间
        Timestamp now = Timestamp.from(Instant.now());
        logger.info("now:" + now);
        inspectionDetailMapper.setEndTime(inspectionDetailId, now);

        //修改巡检点位任务状态
        int inspectionWorkStatus = 2;
        InspectionWork inspectionWork = inspectionWorkMapper.getInspectionWorkById(inspectionDetailMapper.getInspectionWorkIdByDetailId(inspectionDetailId));
        //为避免重复增加，无录音信息时（表示未提交过）才会给完成点位数量加一
        if(inspectionDetailMapper.getCheatMsg(inspectionDetailId) == null || inspectionDetailMapper.getCheatMsg(inspectionDetailId).isEmpty()) {
            int rows5 = inspectionWorkMapper.addNum(inspectionWork.getInspectionWorkId());
        }
        int rows4 = inspectionDetailMapper.setStatus(inspectionDetailId, 2);

        //提交之后判断inspection_work中，对应的这个任务是否全部完成，完成则判断是否有超时，然后修改状态
        if(inspectionWorkMapper.getInspectionWorkNumber(inspectionWork.getInspectionWorkId()) == inspectionWorkMapper.getInspectionWorkFinish(inspectionWork.getInspectionWorkId())){
            //全部完成，先设置完成时间（现在），然后判断是否超过截止时间
            Timestamp endTime = Timestamp.from(Instant.now());
            logger.info("endTime:" + endTime);
            inspectionWorkMapper.setEndTime(endTime, inspectionWork.getInspectionWorkId());

            // 将 endTime 转换为 Instant
            Instant endInstant = inspectionWork.getInspectionStartTime().toInstant();
            // 使用 Duration 增加小时
            Instant newInstant = endInstant.plus(Duration.ofHours(inspectionWork.getInspectionLimitTime()));
            // 将新的 Instant 转换回 Timestamp
            Timestamp finishTime = Timestamp.from(newInstant);
            logger.info("finishTime:" + finishTime);

            //结束时间在截止时间之前，未超时，设为已完成
            inspectionWorkStatus = 2;
            inspectionWorkMapper.setStatus(inspectionWorkStatus, inspectionWork.getInspectionWorkId());
            if(endTime.after(finishTime)) {
                //结束时间在截止时间之后，设为已超时，并将对应的状态为0的巡检点位的状态改为1，已超时
                inspectionWorkStatus = 1;
                inspectionWorkMapper.setStatus(inspectionWorkStatus, inspectionWork.getInspectionWorkId());
                //然后检查所有对应的巡检分配任务，如果结束时间晚于截止时间，则变为1已超时
                List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getDetailByWorkId(inspectionWork.getInspectionWorkId());
                for(InspectionDetail inspectionDetail:inspectionDetailList){
                    //todo 这里进行了修改，注意提交
                    if(inspectionDetail.getInspectionEndTime().after(finishTime)){
                        inspectionDetailMapper.setStatus(inspectionDetail.getInspectionDetailId(), 1);
                    }
                }
            }
        }

        if(isAbnormal){
            inspectionDetailMapper.setStatus(inspectionDetailId, 4);
        }

        //检查文件夹是否存在
        File inspectionDir = new File(inspectionFolder);
        if(!inspectionDir.exists()){
            //创建文件夹
            inspectionDir.mkdirs();
            //创建images文件夹和cheatMsg文件夹
            new File(imagesFolder).mkdirs();
            new File(cheatMsgFolder).mkdirs();
        }

        for (MultipartFile image : images) {
            if (image != null && !image.isEmpty()) {
                try {
                    String fileName = image.getOriginalFilename();
                    image.transferTo(new File(imagesFolder + "\\" + fileName));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //将保存图片的文件夹放到数据库中
            int rows2 = inspectionDetailMapper.setImage(inspectionDetailId, imagesFolder);
        }

        if(cheatMsg != null && !cheatMsg.isEmpty()){
        //保存cheatMsg文件夹
        try{
            String fileName = cheatMsg.getOriginalFilename();
            cheatMsg.transferTo(new File(cheatMsgFolder + "\\" + fileName));
        }catch (IOException e){
            e.printStackTrace();
        }
        //将保存cheatMsg的文件夹路径放到数据库中
        int rows3 = inspectionDetailMapper.setCheatMsg(inspectionDetailId, cheatMsgFolder);
        }

        //获取音频文件的绝对路径，对文件夹中每个文件都进行检测，有一个为"Negative"则判0
        Path path = Paths.get(cheatMsgFolder);

        // 使用 Files 类获取文件夹中的所有文件路径
        List<String> filePaths = Files.list(path)
                .filter(Files::isRegularFile) // 过滤出文件
                .map(Path::toAbsolutePath) // 获取文件的绝对路径
                .map(Path::toString)
                .collect(Collectors.toList());

        if(!filePaths.isEmpty() && filePaths != null) {
            inspectionDetailMapper.setIsCheat(0, inspectionDetailId);
            for (String filePath : filePaths) {
                //读取音频文件，判断是否作弊，0为没作弊，1为作弊
                String isCheatMsg = executePythonScript(scriptPath, filePath, minDb, maxDb);
                if (isCheatMsg.equals("Negative"))
                    inspectionDetailMapper.setIsCheat(1, inspectionDetailId);
            }
        }

        return rows1;
    }

    /**
     * 调用python模型，分析音频文件
     */
    @Override
    public String executePythonScript(String scriptPath, String audioFilePath, double minDb, double maxDb) {
        try {
            // 构建Python命令并传递三个参数
            //ProcessBuilder processBuilder = new ProcessBuilder(
              //       "C:\\Users\\<用户名>\\.virtualenvs\\<虚拟环境名>\\Scripts\\activate && python", scriptPath, audioPath, minDb, maxDb);

            ProcessBuilder processBuilder = new ProcessBuilder(pythonInterpreter, scriptPath, audioFilePath, String.valueOf(minDb), String.valueOf(maxDb));

            // 设置工作目录（如果需要）
            // processBuilder.directory(new File("/path/to/your/python/scripts"));

            // 启动进程
            Process process = processBuilder.start();

            // 获取脚本的输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            StringBuilder output = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line);
            }

            // 等待进程结束
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                // 匹配 "yamnet" 后面的所有字符
                String pattern = "yamnet(.*)";

                // 使用正则表达式查找匹配的部分
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(output.toString());

                // 如果匹配成功
                if (m.find()) {
                    // 输出匹配到的部分
                    logger.info("Matched part: " + m.group(1));
                    return m.group(1);
                } else {
                    logger.error("No match found");
                    return null;
                }
            } else {
                BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                StringBuilder errorOutput = new StringBuilder();
                while ((line = errorReader.readLine()) != null) {
                    errorOutput.append(line);
                }
                throw new RuntimeException("Python脚本执行错误：" + errorOutput.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("调用Python脚本时出错", e);
        }
    }
    
    /**
     * 取出保存图像（返回图片存在nginx里面的文件的http路径）
     */
    @Override
    public List<String> getPictures(int inspectionDetailId){
        String inspectionDetailImg = inspectionDetailMapper.getImg(inspectionDetailId);
        //本地图片路径
        List<String> imagePathList = new ArrayList<>();
        //nginx图片的http路径
        List<String> urlPathList = new ArrayList<>();
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(inspectionDetailImg), "*.{jpg,jpeg,png,gif}")) {
            for (Path entry : stream) {
                imagePathList.add(entry.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        String baseUrl = "http://106.53.100.120:8070/";
        for(String path:imagePathList){
            String urlPath = path.replace("/home/sujianning/nginx/html/", "");
            urlPath = baseUrl + urlPath;
            urlPathList.add(urlPath);
        }
        return urlPathList;
    }

    private boolean isImageFile(File file) {
        String fileName = file.getName().toLowerCase();
        return fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") || fileName.endsWith(".png") || fileName.endsWith(".gif") || fileName.endsWith(".bmp");
    }


    /**
     * 获取点位数据
     */
    @Override
    public List<DataVO> getDetailData(int inspectionGroupId, int inspectionDetailId){
        List<DataVO> dataVOList = new ArrayList<>();
        List<String> attributeList = inspectionGroupMapper.getAscAttributeByGroupId(inspectionGroupId);
        String valueStr = inspectionDetailMapper.getValueStr(inspectionDetailId);
        List<String> valueList = Arrays.stream(valueStr.split("/"))
                .collect(Collectors.toList());
        for(int index = 0; index < valueList.size(); index++){
            DataVO dataVO = new DataVO(attributeList.get(index), valueList.get(index));
            dataVOList.add(dataVO);
        }
        return dataVOList;
    }

    /**
     * 判断某用户是否有分配巡检任务
     */
    @Override
    public boolean existInspectionDetailUser(int userId){
        return !(inspectionDetailMapper.getDetailByUserId(userId).isEmpty() || inspectionDetailMapper.getDetailByUserId(userId) == null);
    }


    /**
     * 判断用户是否为管理员
     */
    @Override
    public boolean isAdmin(int userId){
        return userMapper.getRoleById(userId) == 1 || userMapper.getRoleById(userId) == 2;
    }

    /**
     * 查看所有用户今日巡查，异常，漏检，不合格数之和
     */
    @Override
    public StatusNumVO getAllStatusNumVO(){
        return statisticsUserMapper.getTodayStatusNumVO();
    }

    /**
     * 获取批次内的分配任务
     * @param userId
     * @return List<InspectionVO>
     */
    @Override
    public List<InspectionVO> getInspectionOfBatch(int userId,int batchId) {

        Batch batch = batchMapper.getBatchById(batchId);
        if (batch == null)
            return null;
        List<InspectionVO> inspectionVOList = new ArrayList<>();
        List<Integer> inspectionWorkIdList = new ArrayList<>();
        for (int i = batch.getWorkBeginId();i<=batch.getWorkEndId();i++){
            inspectionWorkIdList.add(i);
        }

        for(int inspectionWorkId:inspectionWorkIdList) {
            InspectionWork inspectionWork = inspectionWorkMapper.getInspectionWorkById(inspectionWorkId);
            if (inspectionWork != null){
                Inspection inspection = inspectionMapper.getInspectionById(inspectionWork.getInspectionId());
                Map map = mapMapper.getMap(inspection.getInspectionMapId());
                InspectionVO inspectionVO = new InspectionVO(map, inspection, inspectionWork);
                inspectionVOList.add(inspectionVO);
            }
        }

        LinkedHashSet<InspectionVO> hashSet = new LinkedHashSet<>(inspectionVOList);
        List<InspectionVO> list = new ArrayList<>(hashSet);
        return list;
    }

    /**
     * 根据inspectionDataId
     * @param inspectionDataId
     * @return InspectionData
     */
    @Override
    public InspectionData getInspectionDataById(int inspectionDataId) {
        return inspectionDataMapper.getInspectionDataById(inspectionDataId);
    }

    /**
     * 查询一个使用模版巡检任务的分配任务
     * @param inspectionId
     * @return InspectionWork
     */
    @Override
    public InspectionWork getInspectionWorkByInspectionId(int inspectionId) {
        return inspectionWorkMapper.getInspectionWorkByInspectionId(inspectionId);
    }

    /**
     * 查询模版巡检任务或者是分配巡检任务是否有使用inspectionGroupId对应的数据组
     * @param inspectionGroupId
     * @return String
     */
    @Override
    public String isUseGroup(int inspectionGroupId) {
        InspectionData inspectionData = inspectionDataMapper.getInspectionDataByGroupId(inspectionGroupId);
        if (inspectionData != null)
            return "数据组正在被巡检模版任务使用，无法删除！";
        InspectionDetail inspectionDetail = inspectionDetailMapper.getInspectionDetailByGroupId(inspectionGroupId);
        if (inspectionDetail != null)
            return "数据组正在被巡检任务使用，无法删除！";
        return null;
    }

    /**
     * 修改巡检任务信息
     * @param inspectionWorkVO
     * @return Integer
     */
    @Override
    public Integer updateInspectionWork(InspectionWorkVO inspectionWorkVO) {
        return inspectionWorkMapper.updateInspectionWork(inspectionWorkVO);
    }

    /**
     * 根据inspectionWorkId查询InspectionWork
     * @param inspectionWorkId
     * @return InspectionWork
     */
    @Override
    public InspectionWork getInspectionWorkById(int inspectionWorkId) {
        return inspectionWorkMapper.getInspectionWorkById(inspectionWorkId);
    }

    /**
     * 根绝inspectionDetailId修改inspectionDetail
     * @param newDetailListVO
     * @return Integer
     */
    @Override
    public Integer updateInspectiondetails(NewDetailListVO newDetailListVO) {
        int row = 1;
        for (NewDetailVO newDetailVO : newDetailListVO.getNewDetails()){
            InspectionDetail inspectionDetail = inspectionDetailMapper.getInspectionDetailById(newDetailVO.getInspectionDetailId());
            if (inspectionDetail != null){
                int status = inspectionDetail.getInspectionDetailStatus();
                if (status != 0 && status != 6 && inspectionDetail.getInspectionGroupId() != newDetailVO.getInspectionGroupId()){
                    row = 0;
                    newDetailVO.setInspectionGroupId(inspectionDetail.getInspectionGroupId());
                }
                if (inspectionGroupMapper.getInspectionGroupByInspectionId(newDetailVO.getInspectionGroupId()) == null)
                    return 2;
                System.out.println(inspectionGroupMapper.getInspectionGroupByInspectionId(newDetailVO.getInspectionGroupId()));
                inspectionDetailMapper.updateInspectionDetail(newDetailVO);
            }
        }
        return row;
    }

    /**
     * 获取批量创建的每一天的具体开始时间
     */
    public static List<Timestamp> getDailyTimestampsWithSpecificTime(Timestamp start, Timestamp end, Timestamp specificTime) {
        List<Timestamp> timestamps = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(start);

        Calendar specificTimeCalendar = Calendar.getInstance();
        specificTimeCalendar.setTime(specificTime);

        int hour = specificTimeCalendar.get(Calendar.HOUR_OF_DAY);
        int minute = specificTimeCalendar.get(Calendar.MINUTE);
        int second = specificTimeCalendar.get(Calendar.SECOND);
        int millisecond = specificTimeCalendar.get(Calendar.MILLISECOND);

        while (!calendar.getTime().after(end)) {
            calendar.set(Calendar.HOUR_OF_DAY, hour);
            calendar.set(Calendar.MINUTE, minute);
            calendar.set(Calendar.SECOND, second);
            calendar.set(Calendar.MILLISECOND, millisecond);

            timestamps.add(new Timestamp(calendar.getTimeInMillis()));
            calendar.add(Calendar.DAY_OF_MONTH, 1);  // 每次加一天
        }
        return timestamps;
    }

    /**
     * 定期更新用户统计表（5分钟）
     */
    @Override
    @Scheduled(fixedRate = 5* 60 *1000)
    public void updateStatistic(){
        //先判断当前时间，如果当前时间为00:00-00:05之间(左闭右开)，则先新建所有userId * unitId的当天的statistic_user项
        //新建用户或者机组时，应该同时在statistics_user表中新建数据
        LocalTime currentTime = LocalTime.now();
        LocalTime firstTime = LocalTime.of(0, 0);
        LocalTime lastTime = LocalTime.of(0, 5);

        if(!currentTime.isBefore(firstTime) && currentTime.isBefore(lastTime)){
            statisticsUserMapper.insertAllUserUnit();
        }

        //此时只需要进行更新操作，而无需进行新建操作
        statisticsUserMapper.updateAllStatistic();
    }

    /**
     * 统计所有机组的数据
     */
    @Override
    public StatisticUnitVO getStatisticUnit(Timestamp startTime, Timestamp endTime) {
        Date startDate = new Date(startTime.getTime());
        Date endDate = new Date(endTime.getTime());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedStartDate = calendar.getTime();  // 获取调整后的时间

        calendar.setTime(endDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedEndDate = calendar.getTime();  // 获取调整后的时间

        //获取时间区域内的任务
        StatisticVO total = statisticsUserMapper.getAllStatistic(adjustedStartDate, adjustedEndDate);
        List<StatisticUnitMidVO> statisticUnitMidVOList = statisticsUserMapper.getStatisticUnitMid(adjustedStartDate, adjustedEndDate);
        List<StatisticClassVO> classes = statisticsUserMapper.getStatisticClasses(adjustedStartDate, adjustedEndDate);

        //然后将StatisticClassVO按照unitId放到statisticUnitMidVOList里面
        // 获取所有在 inspectionDetail 表中存在的 (unitId, classId) 组合
        Set<Pair<Integer, Integer>> validUnitClassPairs = inspectionDetailMapper
                .getAllUnitClassPairs()  // 假设这个方法返回一个包含 (unitId, classId) 的 Set<Pair<Integer, Integer>>
                .stream()
                .collect(Collectors.toSet());

// 过滤 classes 列表，移除不存在于 inspectionDetail 表中的 StatisticClassVO
        List<StatisticClassVO> filteredClasses = classes.stream()
                .filter(classVO -> validUnitClassPairs.contains(new MutablePair<>(classVO.getUnitId(), classVO.getClassId())))
                .collect(Collectors.toList());

// 将 filteredClasses 按 unitId 分组
        java.util.Map<Integer, List<StatisticClassVO>> classesByUnitId = filteredClasses.stream()
                .collect(Collectors.groupingBy(StatisticClassVO::getUnitId));

// 遍历 statisticUnitMidVOList，将 classes 属性填充
        for (StatisticUnitMidVO unit : statisticUnitMidVOList) {
            // 根据 unitId 设置对应的 classes
            unit.setClasses(classesByUnitId.getOrDefault(unit.getUnitId(), List.of()));
        }


        return new StatisticUnitVO(total, statisticUnitMidVOList);
    }

    /**
     * 统计某个机组所有数据
     */
    @Override
    public StatisticOneUnitVO getStatisticOneUnit(int unitId, Timestamp startTime, Timestamp endTime){
        Date startDate = new Date(startTime.getTime());
        Date endDate = new Date(endTime.getTime());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedStartDate = calendar.getTime();  // 获取调整后的时间

        calendar.setTime(endDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedEndDate = calendar.getTime();  // 获取调整后的时间

        //先获取时间区域内某个机组统计数总和
        StatisticVO total = statisticsUserMapper.getUnitStatistic(unitId, adjustedStartDate, adjustedEndDate);
        List<StatisticMemberVO> members = statisticsUserMapper.getMembers(unitId, adjustedStartDate, adjustedEndDate);
        List<StatisticUnitClassVO> classes = statisticsUserMapper.getUnitClass(unitId, adjustedStartDate, adjustedEndDate);

        // 创建一个 Map，用于按 classId 存储 StatisticUnitClassVO
        java.util.Map<Integer, StatisticUnitClassVO> classMap = classes.stream()
                .collect(Collectors.toMap(StatisticUnitClassVO::getClassId, classVO -> classVO));

        // 遍历 members 列表，将每个成员添加到对应的班组
        for (StatisticMemberVO member : members) {
            StatisticUnitClassVO classVO = classMap.get(member.getClassId());
            if (classVO != null) {
                // 如果 classVO 的 members 列表未初始化，进行初始化
                if (classVO.getMembers() == null) {
                    classVO.setMembers(new ArrayList<>());
                }
                // 将成员添加到对应班组的 members 列表
                classVO.getMembers().add(member);
            }
        }

        return new StatisticOneUnitVO(total, classes);
    }

    /**
     * 统计某班组所有成员所有机组的数据
     */
    @Override
    public List<StatisticMemberVO> getStatisticAllUnitClassMember(int classId, Timestamp startTime, Timestamp endTime){
        Date startDate = new Date(startTime.getTime());
        Date endDate = new Date(endTime.getTime());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedStartDate = calendar.getTime();  // 获取调整后的时间

        calendar.setTime(endDate);
        calendar.add(Calendar.HOUR_OF_DAY, -8);  // 减去 8 个小时
        Date adjustedEndDate = calendar.getTime();  // 获取调整后的时间

        return statisticsUserMapper.getAllUnitClassMember(classId, adjustedStartDate, adjustedEndDate);
    }

    /**
     * 保存排班表
     * @param scheduleExcel
     * @return Integer
     */
    @Override
    public Integer uploadScheduleExcel(MultipartFile scheduleExcel) {
        String scheduleDirPath = basePath + "\\schedule\\";

        // 创建目标文件夹对象
        File scheduleDir = new File(scheduleDirPath);

        // 检查文件夹是否存在，不存在则创建
        if (!scheduleDir.exists()) {
            if (!scheduleDir.mkdirs()) {
                System.out.println("文件夹创建失败：" + scheduleDirPath);
                return 0; // 返回失败标识
            }
        }

        // 指定文件名
        String fileName = "schedule.xlsx";
        File destFile = new File(scheduleDirPath + fileName);

        try {
            // 保存文件到目标位置
            scheduleExcel.transferTo(destFile);
            System.out.println("文件保存成功：" + destFile.getAbsolutePath());
            return 1; // 返回成功标识
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件保存失败");
            return 0; // 返回失败标识
        }
    }

    /**
     * 根据排班表来分配任务
     * @param distributeBatchVo
     * @return String
     */
    @Override
    public String distributeInspection(DistributeBatchVo distributeBatchVo) {
        //创建每天的巡检任务
        int inspectionId = distributeBatchVo.getInspectionId();
        int inspectionWorkNumber = distributeBatchVo.getInspectionWorkNumber();
        int inspectionWorkStatus = distributeBatchVo.getInspectionWorkStatus();
        String batchName = distributeBatchVo.getBatchName();
        String inspectionWorkName = distributeBatchVo.getInspectionWorkName();
        Timestamp inspectionStartTime=null;
        Timestamp inspectionEndTime = null;
        //判断是不是第一个startTime
        boolean flag = true;

        List<Integer> rows = new ArrayList<>();

        List<InspectionDetail> inspectionDetails = distributeBatchVo.getInspectionDetails();
        List<ClassMemberVo> classMemberVos = distributeBatchVo.getClassMemberVO();

        String filePath = scheduleDirPath + "/schedule.xlsx";

        // 读取 Excel 文件
        try (FileInputStream fis = new FileInputStream(new File(filePath));
             Workbook workbook = new XSSFWorkbook(fis)) {

            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表

            // 遍历每一行，跳过标题行
            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                Row row = sheet.getRow(i); // 获取当前行

                if (row != null) {
                    // 获取每一列的值
                    int id = (int) row.getCell(0).getNumericCellValue();
                    String startTime = row.getCell(1).getStringCellValue();
                    String endTime = row.getCell(2).getStringCellValue();
                    int groupId = (int) row.getCell(3).getNumericCellValue();

                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                    Timestamp timestamp = new Timestamp(System.currentTimeMillis());


                    String everyDayWorkName = inspectionWorkName + timestamp.toString();
                    Timestamp inspectionWorkStartTime = utilService.convertToTimestamp(startTime);

                    //获取开始与结束时间
                    if (flag){
                        inspectionStartTime = inspectionWorkStartTime;
                        flag = false;
                    }
                    inspectionEndTime = inspectionWorkStartTime;

                    int inspectionLimitTime = utilService.calculateRoundedHours(startTime,endTime);
                    //然后先新增inspection_work表，并取出inspection_work_id
                    int rows1 = addInspectionWork(inspectionWorkStartTime, inspectionLimitTime, everyDayWorkName,
                            inspectionId, inspectionWorkNumber, inspectionWorkStatus);
                    if(rows1 == 0){
                        logger.error("分配巡检任务失败");
                        return "ERROR";
                    }
                    InspectionWork inspectionWork = getInspectionWorkByName(everyDayWorkName);
                    int inspectionWorkId = inspectionWork.getInspectionWorkId();
                    rows.add(inspectionWorkId);
                    List<MemBerVo> memBerVos = utilService.getMemberDetailByClassId(classMemberVos,groupId);
                    //然后用for循环插入inspection_detail表
                    for(InspectionDetail inspectionDetail:inspectionDetails){
                        int inspectionDetailStatus = inspectionDetail.getInspectionDetailStatus();
                        int inspectionDataId = inspectionDetail.getInspectionDataId();
                        int inspectionDetailUser = utilService.getMemberByInspectionDataId(memBerVos,inspectionDataId).getInspectionDetailUser();
                        InspectionData inspectionData = getInspectionDataById(inspectionDataId);
                        int unitId = mapDetailMapper.getMapDetailById(inspectionData.getMapDetailId()).getUnitId();
                        int rows2 = addInspectionDetail(inspectionWorkId, inspectionDataId, groupId, inspectionDetailUser,inspectionDetailStatus,
                                inspectionData.getInspectionGroupId(),inspectionData.getMapDetailId(),inspectionData.getInspectionDataDesc(),inspectionData.getInspectionDataName(),unitId);

                        if(rows2 == 0){
                            logger.error("分配巡检任务失败");
                            return "ERROR";
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace(); // 处理文件读取异常
            return "ABNORMAL";
        }

        //创建批次
        Batch batch = new Batch();
        batch.setIsBatch(distributeBatchVo.getIsBatch());
        batch.setBatchEndTime(inspectionEndTime);
        batch.setBatchStartTime(inspectionStartTime);
        batch.setWorkBeginId(rows.get(0));
        batch.setWorkEndId(rows.get(rows.size()-1));
        batch.setBatchCreateTime(new Timestamp(System.currentTimeMillis()));
        batch.setBatchName(batchName);

        batchService.addBatch(batch);

        logger.info("分配巡检任务失败分配巡检任务成功");
        return "SUCCESS";
    }

    /**
     * 根据NfcMsg来获取数据详情
     * @param nfcMsg
     * @param userId
     * @return List<List<InspectionDetailVO>>
     */
    @Override
    public List<InspectionDetailVO> getInspectionDetailVOByNfcMsg(String nfcMsg, int userId) {
        List<InspectionDetail> inspectionDetailList = inspectionDetailMapper.getInspectionDetailByUserIdAndStatus(userId,0);
        if (inspectionDetailList == null || inspectionDetailList.isEmpty())
            return null;
        inspectionDetailList.removeIf(inspectionDetail -> {
            String mapNfcMsg = mapDetailMapper.getMapDetailById(inspectionDetail.getMapDetailId()).getMapNfcMsg();
            return !nfcMsg.equals(mapNfcMsg);  // 条件不满足时移除元素
        });
        return getInspectionDetailVOList(inspectionDetailList);
    }
}
























